package com.allwees.support.payment.paypal.util;

import com.paypal.api.payments.Amount;
import com.paypal.api.payments.CreditCard;
import com.paypal.api.payments.Details;
import com.paypal.api.payments.FundingInstrument;
import com.paypal.api.payments.Item;
import com.paypal.api.payments.ItemList;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payer;
import com.paypal.api.payments.Payment;
import com.paypal.api.payments.Transaction;
import com.allwees.bs.core.model.order.entity.OrderItemModel;
import com.allwees.bs.core.model.order.entity.OrderModel;
import com.allwees.bs.core.model.payment.enums.EPaymentType;
import com.allwees.core.common.util.MoneyUtil;
import com.allwees.support.payment.EPayMethod;
import com.allwees.support.payment.encryptor.CreditCardEncryptor;
import com.allwees.support.payment.model.CreditCardInfo;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class PayPalUtil {
    private final static String INTENT = "sale";

    public static Payment buildPaypal(OrderModel order, List<? extends OrderItemModel> orderItems) {
        return build(EPayMethod.PAYPAL, order, orderItems, null);
    }

    public static Payment build(EPayMethod payMethod, OrderModel order, List<? extends OrderItemModel> orderItems, CreditCardInfo creditCardInfo) {

        Payer payer = buildPayer(payMethod);

        List<Transaction> transactions = buildTransactions(order, orderItems);

        if (EPayMethod.CREDIT_CARD.equals(payMethod)) {
            payer.setFundingInstruments(buildFundingInstruments(creditCardInfo));
        }

        return new Payment().setIntent(INTENT)
                .setPayer(payer)
                .setTransactions(transactions);
    }

    public static EPaymentType analysisPaymentType(Payment payment) {
        EPaymentType orderPaymentType = null;
        if (EPaymentType.PAYPAL.name().equalsIgnoreCase(payment.getPayer().getPaymentMethod().toUpperCase())) {
            orderPaymentType = EPaymentType.PAYPAL;
        } else {
            FundingInstrument fundingInstrument = CollectionUtils.isEmpty(payment.getPayer().getFundingInstruments()) ? null : payment.getPayer().getFundingInstruments().get(0);
            if (fundingInstrument != null) {
                orderPaymentType = EPaymentType.valueOf(fundingInstrument.getCreditCard().getType().toUpperCase());
            }
        }
        return orderPaymentType;
    }

    /*
     * 支付细节必须填入快递费，subtotal为订单商品总价 支付总和中填入订单总金额 商品列表（item）中填入具体SKU的价格，和购买的数量
     */
    public static List<Transaction> buildTransactions(OrderModel order, List<? extends OrderItemModel> orderItems) {

        Details details = new Details();
        details.setShipping(order.getAmtShipping().toPlainString());
        details.setSubtotal(order.getAmtProduct().toPlainString());

        if (!MoneyUtil.isNullOrZero(order.getAmtShippingInsurance())) {
            details.setInsurance(order.getAmtShippingInsurance().toPlainString());
        }
        if (!MoneyUtil.isNullOrZero(order.getAmtSaleTaxAfterAdd())) {
            details.setTax(order.getAmtSaleTaxAfterAdd().toPlainString());
        }
        Amount amount = new Amount();
        amount.setCurrency(order.getCurrency());
        amount.setTotal(order.getAmt().toPlainString());
        amount.setDetails(details);

        Transaction transaction = new Transaction();
        transaction.setAmount(amount);

        // 添加定制字段（订单ID），用于paypal的webhooks中结算订单
        transaction.setCustom(order.getUuid());

        // 订单编号
        transaction.setDescription(order.getNo());

        //
        transaction.setItemList(buildItems(order, orderItems));

        List<Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);
        return transactions;
    }

    public static ItemList buildItems(OrderModel order, List<? extends OrderItemModel> orderItems) {
        List<Item> items = new ArrayList<>();
        orderItems.forEach(item -> items.add(buildItem(order, item)));
        ItemList itemList = new ItemList();
        itemList.setItems(items);
        return itemList;
    }

    private static Item buildItem(OrderModel order, OrderItemModel orderItem) {
        // 组合支付item
        Item item = new Item();
        // item的名字用商品名称+SKU属性拼接
        item.setName(orderItem.getProductUuid());
        item.setCurrency(order.getCurrency());

        item.setQuantity(orderItem.getQuantity().toString());

        item.setPrice(orderItem.getPrice().toPlainString());
        return item;
    }

    private static List<FundingInstrument> buildFundingInstruments(CreditCardInfo creditCardInfo) {

        List<FundingInstrument> fundingInstruments = new ArrayList<>();

        FundingInstrument fundingInstrument = new FundingInstrument();

        CreditCard creditCard = new CreditCard();
        creditCard.setType(creditCardInfo.getType());
        creditCard.setNumber(CreditCardEncryptor.decrypt(creditCardInfo.getNumber()));
        creditCard.setCvv2(CreditCardEncryptor.decrypt(creditCardInfo.getCvv2()));
        creditCard.setExpireYear(Integer.parseInt(CreditCardEncryptor.decrypt(creditCardInfo.getExpireYear())));
        creditCard.setExpireMonth(Integer.parseInt(CreditCardEncryptor.decrypt(creditCardInfo.getExpireMonth())));

        fundingInstruments.add(fundingInstrument.setCreditCard(creditCard));

        return fundingInstruments;
    }

    private static Payer buildPayer(EPayMethod method) {
        Payer payer = new Payer();
        payer.setPaymentMethod(method.name());
        return payer;
    }

    public static String getApprovalUrl(Iterator<Links> links) {
        while (links.hasNext()) {
            Links link = links.next();
            if (link.getRel().equalsIgnoreCase("approval_url")) {
                // REDIRECT USER TO link.getHref()
                // approval_url为用户支付地址，打开该页面即可进行支付
                return link.getHref();
            }
        }
        return null;
    }

    public static boolean isSuccess(String status) {
        return "approved".equals(status);
    }
}
